#-*-coding:utf-8 -*-
import xlrd3
import numpy as np
import xlsxwriter as xlsw
from tkinter import *
import tkinter.filedialog
import os

root=Tk()
root.title('表格生成')
root.geometry("250x150")
lb=Label(root,text='请选择表格文件')
lb.pack()
lb2=Label(root,text='')
lb2.pack()
lb3=Label(root,text='说明：CAD输出前请用分解以将\n多行文字和多段线分解成直线和文字，\n本程序不识别多行文字和多段线')
lb3.pack()

def main():
    filepath=tkinter.filedialog.askopenfilename(title='打开表格文件',filetypes=[('Excel','*.xls *.xlsx'),('All files','*')],initialdir=os.path.join(os.path.expanduser('~'),"Desktop"),initialfile='直线压力测试.xls')
    
    if filepath=='':
        lb2.config(text='未选择文件')
        return 0
    else:
        lb2.config(text=filepath)
    root.update

    inputxls=xlrd3.open_workbook(filepath)
    A=[]
    table=inputxls.sheet_by_index(0)
    for i in range(table.nrows):
        line=table.row_values(i)
        A.append(line)
    A=np.array(A)
    A=np.delete(A,0,axis=0)

    rowP=0 #类型所在列
    rowX=1 #X所在列
    rowH=4 #字符串高度所在列
    rowY=2 #Y所在列
    rowS=3 #字符串所在列
    rowW=5 #宽度因子所在列
    rowEX=6 #端点X
    rowEY=7
    rowSX=8  #起点X
    rowSY=9
    Largescaleindex=5 #低像素化系数

    Aline=np.empty([1,A.shape[1]],dtype=str) #筛选直线
    for i in range(A.shape[0]):
        if A[i,rowP]=='直线':
            Aline=np.concatenate((Aline,np.expand_dims(A[i,:],axis=0)),axis=0)
    Aline=np.delete(Aline,0,axis=0)

    Atext=np.empty([1,A.shape[1]],dtype=str) #筛选文字
    for i in range(A.shape[0]):
        if A[i,rowP]=='文字':
            Atext=np.concatenate((Atext,np.expand_dims(A[i,:],axis=0)),axis=0)
    Atext=np.delete(Atext,0,axis=0)

    scale=np.median(Atext[:,rowH].astype(np.double)) #比例尺

    AlineL=np.empty([0,A.shape[1]],dtype=str) #筛选竖线
    for i in range(Aline.shape[0]):
        if (abs(Aline[i,rowSX].astype(np.double)-Aline[i,rowEX].astype(np.double))<(0.1*scale)) & (abs(Aline[i,rowSY].astype(np.double)-Aline[i,rowEY].astype(np.double))>scale):
            AlineL=np.concatenate((AlineL,np.expand_dims(Aline[i,:],axis=0)),axis=0)

    AlineH=np.empty([0,A.shape[1]],dtype=str) #筛选横线
    for i in range(Aline.shape[0]):
        if (abs(Aline[i,rowSY].astype(np.double)-Aline[i,rowEY].astype(np.double))<(0.1*scale)) & (abs(Aline[i,rowSX].astype(np.double)-Aline[i,rowEX].astype(np.double))>scale):
            AlineH=np.concatenate((AlineH,np.expand_dims(Aline[i,:],axis=0)),axis=0)

    #直线加点
    Xm=np.empty(0,dtype=np.double)
    Ym=np.empty(0,dtype=np.double)
    for i in range(AlineH.shape[0]):
        Xmline=np.append(np.arange(np.min([AlineH[i,rowSX].astype(np.double),AlineH[i,rowEX].astype(np.double)]),np.max([AlineH[i,rowSX].astype(np.double),AlineH[i,rowEX].astype(np.double)]),scale),np.max([AlineH[i,rowSX].astype(np.double),AlineH[i,rowEX].astype(np.double)]))
        Xm=np.concatenate((Xm,Xmline),axis=None)
        Ym=np.concatenate((Ym,np.ones_like(Xmline)*(AlineH[i,rowSY].astype(np.double)+AlineH[i,rowEY].astype(np.double))/2),axis=None)

    for i in range(AlineL.shape[0]):
        Ymline=np.append(np.arange(np.min([AlineL[i,rowSY].astype(np.double),AlineL[i,rowEY].astype(np.double)]),np.max([AlineL[i,rowSY].astype(np.double),AlineL[i,rowEY].astype(np.double)]),scale),np.max([AlineL[i,rowSY].astype(np.double),AlineL[i,rowEY].astype(np.double)]))
        Ym=np.concatenate((Ym,Ymline),axis=None)
        Xm=np.concatenate((Xm,np.ones_like(Ymline)*(AlineL[i,rowSX].astype(np.double)+AlineL[i,rowEX].astype(np.double))/2),axis=None)

    Xall=np.concatenate((Xm,Atext[:,rowX].astype(np.double)),axis=None)#所有点
    Yall=np.concatenate((Ym,Atext[:,rowY].astype(np.double)),axis=None)

    #创建栅格，取黑
    scale=scale*Largescaleindex #以下处理低像素化
    PXstart=np.min(Xall)
    PYstart=np.max(Yall)
    PXend=np.max(Xall)
    PYend=np.min(Yall)
    Nx=int(np.ceil(abs(PXstart-PXend)/scale)+3)
    Ny=int(np.ceil(abs(PYstart-PYend)/scale)+3)
    Grid=np.zeros([Ny,Nx])

    for i in range(Xall.shape[0]):
        m=int(np.round((Xall[i]-PXstart)/scale)+1)
        n=int(np.round((Yall[i]-PYend)/scale)+1)
        Grid[n,m]=1

    #标记Group
    Grid2=np.zeros([Ny,Nx])
    i=0
    b=True
    Group=np.empty([0,2],dtype=int)
    while(b):
        for j in range(Ny):
            if bool(Grid[j,i]) & (Grid2[j,i]==0):
                Group=np.concatenate((Group,np.expand_dims([j,i],axis=0)),axis=0)
                b=False
                break
        i=i+1

    Ngroup=0 #Group序号
    a=True #全标记判断依据
    while(a): #核心循环，连通检测分离
        Ngroup=Ngroup+1
        b=True
        while(b):
            Group2=np.empty([0,2],dtype=int)
            for i in range(Group.shape[0]):
                if (Grid[Group[i,0]+1,Group[i,1]]==1) & (Grid2[Group[i,0]+1,Group[i,1]]==0):
                    Group2=np.concatenate((Group2,np.expand_dims([Group[i,0]+1,Group[i,1]],axis=0)),axis=0)
                    Grid2[Group[i,0]+1,Group[i,1]]=Ngroup
                if (Grid[Group[i,0]-1,Group[i,1]]==1) & (Grid2[Group[i,0]-1,Group[i,1]]==0):
                    Group2=np.concatenate((Group2,np.expand_dims([Group[i,0]-1,Group[i,1]],axis=0)),axis=0)
                    Grid2[Group[i,0]-1,Group[i,1]]=Ngroup
                if (Grid[Group[i,0],Group[i,1]+1]==1) & (Grid2[Group[i,0],Group[i,1]+1]==0):
                    Group2=np.concatenate((Group2,np.expand_dims([Group[i,0],Group[i,1]+1],axis=0)),axis=0)
                    Grid2[Group[i,0],Group[i,1]+1]=Ngroup
                if (Grid[Group[i,0],Group[i,1]-1]==1) & (Grid2[Group[i,0],Group[i,1]-1]==0):
                    Group2=np.concatenate((Group2,np.expand_dims([Group[i,0],Group[i,1]-1],axis=0)),axis=0)
                    Grid2[Group[i,0],Group[i,1]-1]=Ngroup
            Group=Group2
            if Group2.shape[0]==0:
                b=False
        a=False
        for i in range(Nx*Ny):
            row=int(np.ceil((i+1)/Ny)-1)
            line=int(i+1-row*Ny-1)
            if (Grid[line,row]==1) & (Grid2[line,row]==0):
                a=True
                Group=np.empty([1,2],dtype=int)
                Group[0,0]=line
                Group[0,1]=row
                break

    ##区域分离
    #反像素化
    Groupedge=np.zeros([Ngroup,4])
    for j in range(Ngroup):
        Group=np.empty([0,2],dtype=int)
        for i in range(Nx*Ny):
            row=int(np.ceil((i+1)/Ny)-1)
            line=int(i+1-row*Ny-1)
            if Grid2[line,row]==j+1:
                Group=np.concatenate((Group,np.expand_dims([line,row],axis=0)),axis=0)
        Groupedge[j,0]=(np.min(Group[:,1])-1.5)*scale+PXstart
        Groupedge[j,1]=(np.max(Group[:,1])-0.5)*scale+PXstart
        Groupedge[j,2]=(np.min(Group[:,0])-1.5)*scale+PYend
        Groupedge[j,3]=(np.max(Group[:,0])-0.5)*scale+PYend
    #水平直线
    DatalineH=list()
    for j in range(Ngroup):
        Group=np.empty([0,Aline.shape[1]],dtype=str)
        for i in range(AlineH.shape[0]):
            if (AlineH[i,rowSX].astype(np.double)>=Groupedge[j,0]) & (AlineH[i,rowSX].astype(np.double)<=Groupedge[j,1]) & (AlineH[i,rowSY].astype(np.double)>=Groupedge[j,2]) & (AlineH[i,rowSY].astype(np.double)<=Groupedge[j,3]):
                Group=np.concatenate((Group,np.expand_dims(AlineH[i,:],axis=0)),axis=0)
        DatalineH.append(Group)
    #垂直直线
    DatalineL=list()
    for j in range(Ngroup):
        Group=np.empty([0,Aline.shape[1]],dtype=str)
        for i in range(AlineL.shape[0]):
            if (AlineL[i,rowSX].astype(np.double)>=Groupedge[j,0]) & (AlineL[i,rowSX].astype(np.double)<=Groupedge[j,1]) & (AlineL[i,rowSY].astype(np.double)>=Groupedge[j,2]) & (AlineL[i,rowSY].astype(np.double)<=Groupedge[j,3]):
                Group=np.concatenate((Group,np.expand_dims(AlineL[i,:],axis=0)),axis=0)
        DatalineL.append(Group)
    #文字
    Datatext=list()
    for j in range(Ngroup):
        Group=np.empty([0,Atext.shape[1]],dtype=str)
        for i in range(Atext.shape[0]):
            if (Atext[i,rowX].astype(np.double)>=Groupedge[j,0]) & (Atext[i,rowX].astype(np.double)<=Groupedge[j,1]) & (Atext[i,rowY].astype(np.double)>=Groupedge[j,2]) & (Atext[i,rowY].astype(np.double)<=Groupedge[j,3]):
                Group=np.concatenate((Group,np.expand_dims(Atext[i,:],axis=0)),axis=0)
        Datatext.append(Group)

    scale=scale/Largescaleindex #低像素化结束

    #数值修正
    X=list()
    Y=list()
    for j in range(Ngroup):
        Group=np.empty([0,1],dtype=np.double)
        Group2=np.empty([0,1],dtype=np.double)
        for i in range(Datatext[j].shape[0]):
            Group=np.concatenate((Group,np.expand_dims(Datatext[j][i,rowX].astype(np.double)+len(Datatext[j][i,rowS])*Datatext[j][i,rowW].astype(np.double)*Datatext[j][i,rowH].astype(np.double)*0.5,axis=0)),axis=None)
            Group2=np.concatenate((Group2,Datatext[j][i,rowY].astype(np.double)+Datatext[j][i,rowH].astype(np.double)*0.5),axis=None)
        X.append(Group)
        Y.append(Group2)

    ##形成格子
    #YH,对应rowP
    DatalineHP=list()
    for j in range(Ngroup):
        DatalineH[j][:,rowP]=(DatalineH[j][:,rowSY].astype(np.double)+DatalineH[j][:,rowEY].astype(np.double))/2
        DatalineHP.append(DatalineH[j][:,rowP].astype(np.double))
        DatalineHP[j].sort(axis=0)
    YH=list()
    for j in range(Ngroup):
        Group=np.empty([1],dtype=np.double)
        Group[0]=DatalineHP[j][0]
        for i in range(DatalineH[j].shape[0]):
            if (DatalineHP[j][i]-Group[-1])<(scale/10):
                continue
            Group=np.concatenate((Group,np.expand_dims(DatalineHP[j][i],axis=0)),axis=0)
        YH.append(Group)
        
    #XL,对应rowP
    DatalineLP=list()
    for j in range(Ngroup):
        DatalineL[j][:,rowP]=(DatalineL[j][:,rowSX].astype(np.double)+DatalineL[j][:,rowEX].astype(np.double))/2
        DatalineLP.append(DatalineL[j][:,rowP].astype(np.double))
        DatalineLP[j].sort(axis=0)
    XL=list()
    for j in range(Ngroup):
        Group=np.empty([1],dtype=np.double)
        Group[0]=DatalineLP[j][0]
        for i in range(DatalineL[j].shape[0]):
            if (DatalineLP[j][i]-Group[-1])<(scale/10):
                continue
            Group=np.concatenate((Group,np.expand_dims(DatalineLP[j][i],axis=0)),axis=0)
        XL.append(Group)

    ##小组位置
    GroupstartX=np.zeros([Ngroup,1])
    GroupstartY=np.zeros([Ngroup,1])
    GroupendX=np.zeros([Ngroup,1])
    GroupendY=np.zeros([Ngroup,1])
    for j in range(Ngroup):
        GroupstartX[j]=DatalineLP[j][0]
        GroupstartY[j]=DatalineHP[j][0]
        GroupendX[j]=DatalineLP[j][-1]
        GroupendY[j]=DatalineHP[j][-1]

    #划分Group所在行
    IY=np.argsort(-GroupendY,axis=0)
    GroupendYsortY=-np.sort(-GroupendY,axis=0)
    GroupstartXsortY=GroupstartX[IY]
    GroupendXsortY=GroupendX[IY]
    GroupstartYsortY=GroupstartY[IY]

    formerY=GroupstartYsortY[0]
    lineGroup=int(1)
    GroupH=np.zeros([Ngroup,1])
    for i in range(Ngroup):
        if GroupendYsortY[i]<=formerY:
            lineGroup=lineGroup+1
        GroupH[i]=lineGroup
        formerY=GroupstartYsortY[i]

    #划分Group所在列
    GroupL=np.zeros([Ngroup,1])
    for j in range(lineGroup):
        Group=np.empty([0,2],dtype=np.double)
        for i in range(Ngroup):
            if GroupH[i]==j+1:
                Group=np.concatenate((Group,np.expand_dims([GroupstartXsortY[i],i],axis=0)),axis=0)
        IX=np.argsort(Group[:,0],axis=0)
        Group=Group[IX]
        for i in range(Group.shape[0]):
            GroupL[Group[i,1]]=i+1

    #Group位置
    GroupHL=np.zeros([Ngroup,2],dtype=int)
    for i in range(Ngroup):
        GroupHL[IY[i],0]=GroupH[i]
        GroupHL[IY[i],1]=GroupL[i]

    #Group行列位置
    sizeLine=np.zeros([Ngroup,1])
    for i in range(Ngroup):
        sizeLine[i]=YH[i].shape[0]
    sizeLineMax=int(np.max(sizeLine))
    sizeRow=np.zeros([Ngroup,1])
    for i in range(Ngroup):
        sizeRow[i]=XL[i].shape[0]
    sizeRowMax=int(np.max(sizeRow))
    GroupLR=np.zeros([Ngroup,2])
    GroupLR[:,0]=(GroupHL[:,0]-1)*(sizeLineMax+2)#起点是0
    GroupLR[:,1]=(GroupHL[:,1]-1)*(sizeRowMax+2)
    GroupLR=GroupLR.astype(int)

    savefilepath=tkinter.filedialog.asksaveasfilename(title='保存表格文件',initialdir=os.path.join(os.path.expanduser('~'),"Desktop"),initialfile='输出.xlsx')
    if savefilepath=='':
        lb.config(text='未保存文件,请点击按钮重新运行')
        root.update()
        return 0
    else:
        lb3.config(text='输出文件在:\n'+savefilepath+'\n请等待提示成功再关闭程序')
    root.update()

    #创建xlsx表格
    f=xlsw.Workbook(savefilepath)
    sheet1=f.add_worksheet(u'sheet1')
    ##分配
    Af=np.empty([np.max(GroupHL[:,0])*(sizeLineMax+2),np.max(GroupHL[:,1])*(sizeRowMax+2)],dtype=str)
    for j in range(Ngroup):
        if np.max(X[j])>=max(XL[j]):
            XL[j]=np.concatenate((XL[j],np.max(X[j])+1),axis=None)
        if np.min(X[j])<min(XL[j]):
            XL[j]=np.concatenate((np.min(X[j])+1,XL[j]),axis=None)
        if np.max(Y[j])>=max(YH[j]):
            YH[j]=np.concatenate((YH[j],np.max(Y[j])+1),axis=None)
        if np.min(Y[j])<min(YH[j]):
            YH[j]=np.concatenate((np.min(Y[j])+1,YH[j]),axis=None)
        for l in range(YH[j].shape[0]-1):
            for r in range(XL[j].shape[0]-1):
                Group=np.empty([0],dtype=str)
                Group2=np.empty([0],dtype=np.double)
                for i in range(Datatext[j].shape[0]):
                    if (X[j][i]>=XL[j][r]) & (X[j][i]<XL[j][r+1]) & (Y[j][i]>=YH[j][l]) & (Y[j][i]<YH[j][l+1]):
                        Group=np.concatenate((Group,Datatext[j][i,rowS]),axis=None)
                        Group2=np.concatenate((Group2,Y[j][i]),axis=None)
                if Group2.shape[0]==0:
                    continue
                I=np.argsort(-Group2,axis=0)
                Group=Group[I]
                String=""
                for i in range(Group2.shape[0]):
                    String=String+Group[i]
                sheet1.write(GroupLR[j,0]+(YH[j].shape[0]-l-2),GroupLR[j,1]+r,String)
    f.close()

    lb.config(text='成功！')


btn=Button(root,text='选取表格文件',command=main)
btn.pack()
main()
root.mainloop()
# np.set_printoptions(threshold=np.inf)
# D:\Projects\Python\
# print(Af[7,3].dtype)
# print(GroupL) 